class AiClient : public std::enable_shared_from_this<AiClient>
{
	using AddDataCallback = std::function<void(std::string_view data)>;
	using SendDataCallback = std::function<void()>;
	using FinishDataCallback = std::function<void()>;

	::boost::asio::io_context& _ioc;
	const char* _host = nullptr;
	const char* _port = nullptr;
	::boost::asio::ip::tcp::resolver _resolver;
	::boost::beast::tcp_stream _stream;
	::boost::beast::http::request<::boost::beast::http::string_body> _req;
	::boost::beast::http::response_parser<::boost::beast::http::string_body> _parser;
	::boost::beast::flat_buffer _buffer;
	size_t _bodyProcessed = 0;
	std::chrono::seconds _timeout = std::chrono::seconds(30);
	AddDataCallback _addDataCallback; 
	SendDataCallback _sendDataCallback; 
	FinishDataCallback _finishDataCallback;

public:
	AiClient(::boost::asio::io_context& ioc, const char* host, const char* port);
	~AiClient();

	void post(const std::string& target, const std::string& body);
	void setAddDataCallback(AddDataCallback callback);
	void setSendDataCallback(SendDataCallback callback);
	void setFinishDataCallback(FinishDataCallback callback);

private:
	void onResolve(::boost::beast::error_code ec, ::boost::asio::ip::tcp::resolver::results_type results);
	void onConnect(::boost::beast::error_code ec, ::boost::asio::ip::tcp::resolver::results_type::endpoint_type);
	void onWrite(::boost::beast::error_code ec, size_t);
	void onReadHeader(::boost::beast::error_code ec, size_t);
	void onReadBody(::boost::beast::error_code ec, size_t);
	void fail(::boost::beast::error_code ec, const char* what);
};
